<?

class bf_cache {

	private $opts;

	public function __construct($options = array()) {

		$this->opts = array_merge(array(
			'location' => dirname(__FILE__) . '/../../cache/',
			'value-timeout' => 60*3, // 3 minutes
		), $options);

		if (!preg_match('/\/$/', $this->opts['location']))
			$this->opts['location'] .= '/';
		$server_name = (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost');
		$this->opts['location'] .= md5($server_name) . '/';
	}

	public function __destruct() {
	}

	protected function internal_key($key) {
		return array(
			'directory' => $this->opts['location'] . preg_replace('/([0-9a-f]{2})/i', '${1}/', sprintf('%08x', crc32($key))),
			'file' => md5($key),
		);
	}

	public function get($key, $default_value = false, $is_object = false) {
		$loc = $this->internal_key($key);
		$fname = $loc['directory'] . $loc['file'];
		if (($fp = @fopen($fname, 'r'))) {
			@flock($fp, LOCK_SH);
			$data = @fread($fp, filesize($fname));
			@flock($fp, LOCK_UN);
			@fclose($fp);
			if ($is_object) {
				$data = json_decode($data, false);
				if (@$data->{'expiration-time'} == -1 || @$data->{'expiration-time'} > time())
					return $data->value;
			} else {
				$data = json_decode($data, true);
				if (@$data['expiration-time'] == -1 || @$data['expiration-time'] > time())
					return $data['value'];
			}
		}
		return $default_value;
	}

	public function set($key, $value, $timeout = false) {
		if ($timeout === false)
			$timeout = $this->opts['value-timeout'];
		$loc = $this->internal_key($key);
		@mkdir($loc['directory'], 0777, true);
		return (@file_put_contents(
			$loc['directory'] . $loc['file'],
			json_encode(array(
				'expiration-time' => time() + $timeout,
				'value' => $value,
			)),
			LOCK_EX
		) === false ? false : true);
	}

	public function clear($key) {
		$loc = $this->internal_key($key);
		$fname = $loc['directory'] . $loc['file'];
		@unlink($fname);
	}
}

?>